﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SlimDX;
using SlimDX.Direct3D11;
using SlimDX.DXGI;
using SlimDX.Windows;
using SlimDX.D3DCompiler;
using Device = SlimDX.Direct3D11.Device;
using SpriteTextRenderer;
using SlimDX.DirectWrite;
using SpriteTextRenderer.SlimDX;
using System.Drawing;
using System.Diagnostics;
namespace Sample
{
    class SlimDXSample
    {
        Device device;
        SwapChain swapChain;
        RenderTargetView renderView;
        SpriteTextRenderer.SlimDX.SpriteRenderer sprite;
        public void Run()
        {
            var form = new RenderForm(Helpers.GetFormTitle("SlimDX"));
            form.Resize += form_Resize;
            var desc = new SwapChainDescription()
            {
                BufferCount = 1,
                ModeDescription = new ModeDescription(form.ClientSize.Width, form.ClientSize.Height, new Rational(60, 1), Format.R8G8B8A8_UNorm),
                IsWindowed = true,
                OutputHandle = form.Handle,
                SampleDescription = new SampleDescription(1, 0),
                SwapEffect = SwapEffect.Discard,
                Usage = Usage.RenderTargetOutput
            };
            
            Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, desc, out device, out swapChain);
            device.Factory.SetWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAll);
            Resize(form.ClientSize);

            sprite = new SpriteTextRenderer.SlimDX.SpriteRenderer(device);
            var textBlock = new SpriteTextRenderer.SlimDX.TextBlockRenderer(sprite, "Arial", FontWeight.Bold, SlimDX.DirectWrite.FontStyle.Normal, FontStretch.Normal, 16);

            var sdxTexture = Texture2D.FromFile(device, "sdx.png");
            var srvTexture = new ShaderResourceView(device, sdxTexture);
            FrameMonitor frameMonitor = new FrameMonitor();
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            MessagePump.Run(form, () =>
            {
                double totalMillisec = stopWatch.Elapsed.TotalMilliseconds;
                frameMonitor.Tick();
                device.ImmediateContext.ClearRenderTargetView(renderView, Color.DarkBlue);

                textBlock.DrawString("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + Environment.NewLine + "abcdefghijklmnopqrstuvwxyz", Vector2.Zero, new Color4(1.0f, 1.0f, 0.0f));
                textBlock.DrawString("SDX SpriteTextRenderer sample" + Environment.NewLine + "(using SlimDX)", new RectangleF(0, 0, form.ClientSize.Width, form.ClientSize.Height),
                    SpriteTextRenderer.TextAlignment.Right | SpriteTextRenderer.TextAlignment.Bottom, new Color4(1.0f, 1.0f, 0.0f));

                textBlock.DrawString(frameMonitor.FPS.ToString("f2") + " FPS", new System.Drawing.RectangleF(0, 0, form.ClientSize.Width, form.ClientSize.Height),
                 SpriteTextRenderer.TextAlignment.Right | SpriteTextRenderer.TextAlignment.Top, new Color4(1.0f, 1.0f, 1.0f, 1.0f));

                sprite.Draw(srvTexture, new Vector2(300, 170), new Vector2(150, 150), new Vector2(75, 75), new Radians(totalMillisec / 1000.0), CoordinateType.Absolute);
                sprite.Draw(srvTexture, new Vector2(380, 320), new Vector2(150, 150), new Vector2(50, 50), new Degrees(-totalMillisec / 8), CoordinateType.Absolute);

                sprite.Flush();

                swapChain.Present(1, PresentFlags.None);
            });
            srvTexture.Dispose();
            sdxTexture.Dispose();
            textBlock.Dispose();
            renderView.Dispose();
            device.Dispose();
            swapChain.Dispose();
        }
        void form_Resize(object sender, EventArgs e)
        {
            RenderForm renderForm = (sender as RenderForm);
            Resize(renderForm.ClientSize);
        }

        void Resize(System.Drawing.Size size)
        {
            Resize(new Vector2(size.Width, size.Height));
        }

        void Resize(Vector2 size)
        {
            if (renderView != null)
                renderView.Dispose();

            swapChain.ResizeBuffers(1, (int)size.X, (int)size.Y, Format.R8G8B8A8_UNorm, SwapChainFlags.None);
            Texture2D backBuffer = Texture2D.FromSwapChain<Texture2D>(swapChain, 0); 
            renderView = new RenderTargetView(device, backBuffer);
            backBuffer.Dispose();

            device.ImmediateContext.Rasterizer.SetViewports(new Viewport(0, 0, (int)size.X, (int)size.Y, 0.0f, 1.0f));
            device.ImmediateContext.OutputMerger.SetTargets(renderView);

            if (sprite != null)
                sprite.RefreshViewport();
        }
    }
}
